// 扩展vue原有的功能：全局组件，自定义指令，挂载原型方法
// vue2.0插件写法要素：导出一个函数，有install函数（参数里有vue构造函数，可以在vue基础之上扩展）
// vue3.0插件写法要素：导出一个函数，有install函数（参数里有app实例，可以在app基础之上扩展）
// 导入默认图片
import defaultImg from '@/assets/images/200.png'
// context（）含参数1：目录 参数2：是否加载子目录， 参数3：加载文件的匹配正则
const importFn = require.context('./', false, /\.vue$/) // require提供的方法
// console.log(importFn.keys())
export default {
  install (app) {
    // 在app实例上进行挂载，app提供了component方法，directive方法，
    // 如果要挂载原型方法，app.config.globalProperties
    // 遍历文件路径数组
    importFn.keys().forEach(path => {
      // 导入组件
      const component = importFn(path).default // 将文件遍历导入
      // 注册
      app.component(component.name, component)
    })
    // 定 义自定义指令
    defineDirective(app)
  }
}

// 定义指令
const defineDirective = (app) => {
  // 定义图片懒加载
  app.directive('lazy', {
    // 配置指令选项
    // 图片懒加载原理 ：先存储图片地址，不妨到标签的src上，避免发起请求
    // 当图片进入可视区，再为图片加上src。发起请求
    // vue2监听使用指令的DOM是否创建好，使用钩子函数 inserted
    // vue3 指令拥有的钩子和组件生命周期钩子一致，使用钩子onMounted
    mounted (el, binding) {
      // 创建一个观察，将当前元素添加入观察 是否进入可视区
      const observe = new IntersectionObserver(([{ isIntersecting }]) => { // 参1回调 参2配置选项
        if (isIntersecting) { // 通过isIntersecting判断是否进入可视区
          // 第一次进入可视区就可以停止了，不需要执行多次
          observe.unobserve(el) // 观察1次就停止观察
          // 图片地址会先绑定到指令上面
          el.src = binding.value // binding.value就是绑定的值
          // 处理图片加载失败（绑定图片加载失败事件）
          el.onerror = () => { // 监听图片加载失败事件
            el.src = defaultImg // 设置默认图片
          }
          // 监听图片加载失败，设置默认图片代替
        }
      }, {
        threshold: 0
      })
      observe.observe(el) // 开启观察
    }
  })
}
